package logger

import (
	"io"
	"io/fs"
	"log"
	"os"
	"runtime/debug"
	"strconv"
	"time"
)

var (
	logFile     io.Writer
	logPath     string
	ymdStr      string
	filePath    string
	logSize     int64 = 10240000
	fileIdx     string
	fileInfo    fs.FileInfo
	debugLogger *log.Logger
	infoLogger  *log.Logger
	warnLogger  *log.Logger
	errorLogger *log.Logger
)

func InitLog(logbasePath string) {
	var (
		err      error
		flag     = log.Ldate | log.Ltime
		preStr   = []string{"[DEBUG]", "[INFO]", "[WARN]", "[ERROR]"}
		levelArr = []string{"_debug", "_info", "_warn", "_error"}
	)
	logPath = logbasePath
	ymdStr = time.Now().Format("2006-01-02")
	for idx, level := range levelArr {
		filePath = logPath + ymdStr + level + ".log"
		// 判断是否存在当前日期的日志文件，不存在则创建
		if fileInfo, err = os.Stat(filePath); err == nil {
			// 存在文件，判断日志文件大小是否超出限制
			if fileInfo.Size() < logSize {
				// 没有超出大小限制，打开当前文件
				logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
			} else {
				// 超出大小限制，轮询出当前日期、级别的日志文件中最大的索引值
				for i := 0; i < 100; i++ {
					fileIdx = strconv.Itoa(i)
					filePath = logPath + ymdStr + level + "_" + fileIdx + ".log"
					// 判断当前日期、级别的日志文件是否存在
					if _, err = os.Stat(filePath); err != nil && os.IsNotExist(err) {
						// 不存在，则将当前日志文件重命名
						_ = os.Rename(logPath+ymdStr+level+".log", filePath)
						// 不存在，则创建一个当前日期、级别、索引的日志文件并打开
						logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
						break
					}
				}
			}
		} else {
			// 不存在，创建一个当前日期、级别的日志文件并打开
			logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
		}
		switch idx {
		case 0:
			debugLogger = log.New(logFile, preStr[0], flag)
		case 1:
			infoLogger = log.New(logFile, preStr[1], flag)
		case 2:
			warnLogger = log.New(logFile, preStr[2], flag)
		case 3:
			errorLogger = log.New(logFile, preStr[3], flag)
		}
	}
}

func Debug(v ...interface{}) {
	checkLogFileStat("_debug")
	debugLogger.Println(v...)
}

func Info(v ...interface{}) {
	checkLogFileStat("_info")
	infoLogger.Println(v...)
}

func Warn(v ...interface{}) {
	checkLogFileStat("_warn")
	warnLogger.Println(v...)
}

func Error(v ...interface{}) {
	checkLogFileStat("_error")
	errorLogger.Println(v...)
	errorLogger.Printf("%s", debug.Stack())
}

// checkLogFileStat 检查日志文件否存在，不存在则创建
func checkLogFileStat(level string) {
	var err error
	ymdStr = time.Now().Format("2006-01-02")
	filePath = logPath + ymdStr + level + ".log"
	// 判断是否存在当前日期的日志文件，不存在则创建
	if fileInfo, err = os.Stat(filePath); err == nil {
		// 存在文件，判断日志文件大小是否超出限制
		if fileInfo.Size() < logSize {
			// 没有超出大小限制，打开当前文件
			logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
		} else {
			// 超出大小限制，轮询出当前日期、级别的日志文件中最大的索引值
			for i := 0; i < 100; i++ {
				fileIdx = strconv.Itoa(i)
				filePath = logPath + ymdStr + level + "_" + fileIdx + ".log"
				// 判断当前日期、级别的日志文件是否存在
				if _, err = os.Stat(filePath); err != nil && os.IsNotExist(err) {
					// 不存在，则将当前日志文件重命名
					_ = os.Rename(logPath+ymdStr+level+".log", filePath)
					// 不存在，则创建一个当前日期、级别、索引的日志文件并打开
					logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
					break
				}
			}
		}
	} else {
		// 不存在，创建一个当前日期、级别的日志文件并打开
		logFile, _ = os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
	}
}
